package com.tanhua.server.service;

import cn.hutool.core.bean.BeanUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.PeachVoiceApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.mongo.PeachVoice;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.PeachVoiceVo;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import javafx.scene.effect.InnerShadowBuilder;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Service
public class PeachblossomService {

    @DubboReference
    private PeachVoiceApi peachVoiceApi;

    @Autowired
    private FastFileStorageClient client;

    @Autowired
    private FdfsWebServer webServer;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @DubboReference
    private UserInfoApi userInfoApi;

    //发送语音
    public void sendVoice(MultipartFile soundFile) throws IOException {
        if (soundFile.isEmpty()) {
            //前端没有传文件过来，抛出异常
            throw new BusinessException(ErrorResult.error());
        }
        //语音文件名字
        String filename = soundFile.getOriginalFilename();
        //获取语音文件后缀名,即文件类型
        filename = filename.substring(filename.lastIndexOf(".") + 1);
        //上传到fastdfs，获取存储地址
        StorePath storePath = client.uploadFile(soundFile.getInputStream(), soundFile.getSize(), filename, null);
        String voicePath = webServer.getWebServerUrl() + storePath.getFullPath();
        PeachVoice peachVoice = new PeachVoice();
        peachVoice.setVoiceUrl(voicePath);
        peachVoice.setUserId(UserHolder.getUserId());
        //调用API发送语音
        String voiceId = peachVoiceApi.save(peachVoice);
        if (voiceId.isEmpty()) {
            throw new BusinessException(ErrorResult.error());
        }
    }

    /**
     * @return: com.tanhua.model.vo.PeachVoiceVo
     * @description: 接收语音
     * @author: Mr.ChiZi
     * @date: 2021/11/27 6:45 下午
     */
    public PeachVoiceVo receiveVoice() {
        // 判断用户今日是否阅读过语音
        Long userId = UserHolder.getUserId();
        String key = Constants.VOICE_NUMBER + userId;
        //剩余阅读次数
        String number = redisTemplate.opsForValue().get(key);

        if (StringUtils.isEmpty(number)) {
            // 今天没阅读过语音，创建redis hash字段，存储阅读次数10次,设置存活时间
            init(key);
            number = "9";
        }
        Integer remainingTimes = Integer.valueOf(number);

        // 判断用户今日是否还有语音阅读次数
        if (remainingTimes < 0) {
            // 没有阅读次数，抛出异常，自定义一个异常
            throw new BusinessException(ErrorResult.voiceError());
        }

        // 还有阅读次数
        // 调用api的统计函数，随机抽取一条没被读过的语音,排除自己的语音
        PeachVoice peachVoice = peachVoiceApi.randomVoice(1, userId);
        // 判断语音是否存在
        if (BeanUtil.isEmpty(peachVoice)) {
            // 语音不存在，抛出异常
            throw new BusinessException(ErrorResult.error());
        }
        // 语音存在
        // 根据用户ID查询用户详情
        Long voiceUserId = peachVoice.getUserId();
        UserInfo userInfo = userInfoApi.findById(voiceUserId);
        // 构建vo对象
        PeachVoiceVo peachVoiceVo = PeachVoiceVo.init(userInfo, peachVoice, remainingTimes);

        // 语音阅读成功，从redis减少一次语音阅读次数
        //todo 这一步假如redis的键这个时候失效了，会自动生成key和值？值是多少，但是没有失效时间
        // 假如原先没有这个键，decrement执行后会自动生成一个，value默认是0，执行后value是-1，不会设置存活时间
        // todo 解决方法，判断key有没有设置过期时间，没有说明key失效了，给他初始化次数
        redisTemplate.opsForValue().decrement(key, 1);
        if (redisTemplate.opsForValue().getOperations().getExpire(key) < 0) {
            init(key);
            number = "9";
        }
        //todo 语音阅后即焚
        peachVoiceApi.remove(peachVoice);
        return peachVoiceVo;
    }

    public void init(String key) {
        //todo 过期时间是24小时还是当天有效
        // 今天没阅读过语音，创建redis hash字段，存储阅读次数10次,存活时间
        redisTemplate.opsForValue().set(key, "9", 1L, TimeUnit.DAYS);
    }
}
